package main

import (
	"context"
	"os"
	"time"

	"github.com/go-kratos/kratos/v2/log"

	"gitee.com/opentelemetry/traces-basic/bus"
	"github.com/go-kratos/kratos/v2/middleware/tracing"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
	"go.opentelemetry.io/otel/trace"
)

func main() {
	//1、tracer provider追踪提供程序，启动程序初始化一次
	//2、tracer 有tracer provider 初始化
	//3、有tracer开启span
	logger := log.With(log.NewStdLogger(os.Stdout),
		"ts", log.DefaultTimestamp,
		"caller", log.DefaultCaller,
		"service.name", "服务名：opentelemetry",
		"trace.id", tracing.TraceID(),
		"span.id", tracing.SpanID(),
	)
	initProvider(logger)
	tracer := otel.Tracer("main-tracer")
	ctx := context.Background()
	ctx2, span := tracer.Start(ctx, "main", trace.WithAttributes(attribute.String("package", "main")))
	defer span.End()
	//和main是父子关系
	busTracer := otel.Tracer("bus-tracer")
	busObj := bus.NewBus(busTracer)
	for i := 0; i < 5; i++ {
		//加 和 乘 是兄弟关系
		busObj.Sum(ctx2, i, i+1)
		busObj.Product(ctx, i, i+1)
		<-time.After(time.Microsecond * 300)
	}
	log.Info("结束")
	time.Sleep(1 * time.Second)
}

func initProvider(logger log.Logger) func(ctx context.Context) error {
	//1、初始化添加到Provider的资源信息
	res, err := resource.New(context.Background(), resource.WithAttributes( //添加一些属性
		semconv.ServiceName("服务名称：tracer-basic"),
		semconv.ServiceVersion("1.0.0"),
		attribute.String("env", "dev"),
	), resource.WithOS(), resource.WithHost()) //系统信息
	if err != nil {
		log.Fatal(err)
	}
	//初始化导出器exporter,http/grpc/stdout
	tracerExport, err := stdouttrace.New(stdouttrace.WithWriter(log.NewWriter(logger))) //标准输出TODO 是不是可以传入Log
	if err != nil {
		log.Fatal(err)
	}
	bsp := sdktrace.NewBatchSpanProcessor(tracerExport)
	tracerProvider := sdktrace.NewTracerProvider(
		sdktrace.WithSampler(sdktrace.AlwaysSample()), //总是采集
		sdktrace.WithResource(res),
		sdktrace.WithSpanProcessor(bsp),
	)
	otel.SetTracerProvider(tracerProvider)
	//如果需要考虑传播，就需要这么设置一下
	otel.SetTextMapPropagator(propagation.Baggage{})
	//关闭时调用？
	return tracerProvider.Shutdown
}
